package cn.cxyxj.study.webflux03.authentication.account;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.server.authentication.ServerAuthenticationConverter;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;

/**
 * 用户名密码登录参数转换
 * @Author: cxyxj
 */
public class UserNamePasswordJsonAuthenticationConverter implements ServerAuthenticationConverter {

    @Override
    public Mono<Authentication> convert(ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        MediaType mediaType = request.getHeaders().getContentType();
        if (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType)) {
            ObjectMapper mapper = new ObjectMapper();
            HttpMessageReader<Object> messageReader = new DecoderHttpMessageReader<>(new Jackson2JsonDecoder(mapper));
            ServerRequest serverRequest = ServerRequest.create(exchange, Arrays.asList(messageReader));
            return serverRequest.bodyToMono(UserNamePasswordModel.class).map(m -> new UsernamePasswordAuthenticationToken(m.getUsername(),m.getPassword()));
        } else {
            // 这里可以选择抛出异常
            throw new RuntimeException("请求方式异常");
            //return Mono.empty();
        }
    }

    static class UserNamePasswordModel {
        private String username;
        private String password;

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }
    }
}